# -*- perl -*-
#
# Pure Perl implementation of the same CRC64 implementation used
# elsewhere in NASM.
#
# Note: Perl may have 32- or 64-bit integers; we need to handle both
# without overflowing into floating point (yuck), so handle them as
# pairs of 32-bit numbers.  Ordering is BIGENDIAN.
#

@crc64_tab = (
    [0x00000000, 0x00000000], [0x7ad870c8, 0x30358979],
    [0xf5b0e190, 0x606b12f2], [0x8f689158, 0x505e9b8b],
    [0xc038e573, 0x9841b68f], [0xbae095bb, 0xa8743ff6],
    [0x358804e3, 0xf82aa47d], [0x4f50742b, 0xc81f2d04],
    [0xab28ecb4, 0x6814fe75], [0xd1f09c7c, 0x5821770c],
    [0x5e980d24, 0x087fec87], [0x24407dec, 0x384a65fe],
    [0x6b1009c7, 0xf05548fa], [0x11c8790f, 0xc060c183],
    [0x9ea0e857, 0x903e5a08], [0xe478989f, 0xa00bd371],
    [0x7d08ff3b, 0x88be6f81], [0x07d08ff3, 0xb88be6f8],
    [0x88b81eab, 0xe8d57d73], [0xf2606e63, 0xd8e0f40a],
    [0xbd301a48, 0x10ffd90e], [0xc7e86a80, 0x20ca5077],
    [0x4880fbd8, 0x7094cbfc], [0x32588b10, 0x40a14285],
    [0xd620138f, 0xe0aa91f4], [0xacf86347, 0xd09f188d],
    [0x2390f21f, 0x80c18306], [0x594882d7, 0xb0f40a7f],
    [0x1618f6fc, 0x78eb277b], [0x6cc08634, 0x48deae02],
    [0xe3a8176c, 0x18803589], [0x997067a4, 0x28b5bcf0],
    [0xfa11fe77, 0x117cdf02], [0x80c98ebf, 0x2149567b],
    [0x0fa11fe7, 0x7117cdf0], [0x75796f2f, 0x41224489],
    [0x3a291b04, 0x893d698d], [0x40f16bcc, 0xb908e0f4],
    [0xcf99fa94, 0xe9567b7f], [0xb5418a5c, 0xd963f206],
    [0x513912c3, 0x79682177], [0x2be1620b, 0x495da80e],
    [0xa489f353, 0x19033385], [0xde51839b, 0x2936bafc],
    [0x9101f7b0, 0xe12997f8], [0xebd98778, 0xd11c1e81],
    [0x64b11620, 0x8142850a], [0x1e6966e8, 0xb1770c73],
    [0x8719014c, 0x99c2b083], [0xfdc17184, 0xa9f739fa],
    [0x72a9e0dc, 0xf9a9a271], [0x08719014, 0xc99c2b08],
    [0x4721e43f, 0x0183060c], [0x3df994f7, 0x31b68f75],
    [0xb29105af, 0x61e814fe], [0xc8497567, 0x51dd9d87],
    [0x2c31edf8, 0xf1d64ef6], [0x56e99d30, 0xc1e3c78f],
    [0xd9810c68, 0x91bd5c04], [0xa3597ca0, 0xa188d57d],
    [0xec09088b, 0x6997f879], [0x96d17843, 0x59a27100],
    [0x19b9e91b, 0x09fcea8b], [0x636199d3, 0x39c963f2],
    [0xdf7adabd, 0x7a6e2d6f], [0xa5a2aa75, 0x4a5ba416],
    [0x2aca3b2d, 0x1a053f9d], [0x50124be5, 0x2a30b6e4],
    [0x1f423fce, 0xe22f9be0], [0x659a4f06, 0xd21a1299],
    [0xeaf2de5e, 0x82448912], [0x902aae96, 0xb271006b],
    [0x74523609, 0x127ad31a], [0x0e8a46c1, 0x224f5a63],
    [0x81e2d799, 0x7211c1e8], [0xfb3aa751, 0x42244891],
    [0xb46ad37a, 0x8a3b6595], [0xceb2a3b2, 0xba0eecec],
    [0x41da32ea, 0xea507767], [0x3b024222, 0xda65fe1e],
    [0xa2722586, 0xf2d042ee], [0xd8aa554e, 0xc2e5cb97],
    [0x57c2c416, 0x92bb501c], [0x2d1ab4de, 0xa28ed965],
    [0x624ac0f5, 0x6a91f461], [0x1892b03d, 0x5aa47d18],
    [0x97fa2165, 0x0afae693], [0xed2251ad, 0x3acf6fea],
    [0x095ac932, 0x9ac4bc9b], [0x7382b9fa, 0xaaf135e2],
    [0xfcea28a2, 0xfaafae69], [0x8632586a, 0xca9a2710],
    [0xc9622c41, 0x02850a14], [0xb3ba5c89, 0x32b0836d],
    [0x3cd2cdd1, 0x62ee18e6], [0x460abd19, 0x52db919f],
    [0x256b24ca, 0x6b12f26d], [0x5fb35402, 0x5b277b14],
    [0xd0dbc55a, 0x0b79e09f], [0xaa03b592, 0x3b4c69e6],
    [0xe553c1b9, 0xf35344e2], [0x9f8bb171, 0xc366cd9b],
    [0x10e32029, 0x93385610], [0x6a3b50e1, 0xa30ddf69],
    [0x8e43c87e, 0x03060c18], [0xf49bb8b6, 0x33338561],
    [0x7bf329ee, 0x636d1eea], [0x012b5926, 0x53589793],
    [0x4e7b2d0d, 0x9b47ba97], [0x34a35dc5, 0xab7233ee],
    [0xbbcbcc9d, 0xfb2ca865], [0xc113bc55, 0xcb19211c],
    [0x5863dbf1, 0xe3ac9dec], [0x22bbab39, 0xd3991495],
    [0xadd33a61, 0x83c78f1e], [0xd70b4aa9, 0xb3f20667],
    [0x985b3e82, 0x7bed2b63], [0xe2834e4a, 0x4bd8a21a],
    [0x6debdf12, 0x1b863991], [0x1733afda, 0x2bb3b0e8],
    [0xf34b3745, 0x8bb86399], [0x8993478d, 0xbb8deae0],
    [0x06fbd6d5, 0xebd3716b], [0x7c23a61d, 0xdbe6f812],
    [0x3373d236, 0x13f9d516], [0x49aba2fe, 0x23cc5c6f],
    [0xc6c333a6, 0x7392c7e4], [0xbc1b436e, 0x43a74e9d],
    [0x95ac9329, 0xac4bc9b5], [0xef74e3e1, 0x9c7e40cc],
    [0x601c72b9, 0xcc20db47], [0x1ac40271, 0xfc15523e],
    [0x5594765a, 0x340a7f3a], [0x2f4c0692, 0x043ff643],
    [0xa02497ca, 0x54616dc8], [0xdafce702, 0x6454e4b1],
    [0x3e847f9d, 0xc45f37c0], [0x445c0f55, 0xf46abeb9],
    [0xcb349e0d, 0xa4342532], [0xb1eceec5, 0x9401ac4b],
    [0xfebc9aee, 0x5c1e814f], [0x8464ea26, 0x6c2b0836],
    [0x0b0c7b7e, 0x3c7593bd], [0x71d40bb6, 0x0c401ac4],
    [0xe8a46c12, 0x24f5a634], [0x927c1cda, 0x14c02f4d],
    [0x1d148d82, 0x449eb4c6], [0x67ccfd4a, 0x74ab3dbf],
    [0x289c8961, 0xbcb410bb], [0x5244f9a9, 0x8c8199c2],
    [0xdd2c68f1, 0xdcdf0249], [0xa7f41839, 0xecea8b30],
    [0x438c80a6, 0x4ce15841], [0x3954f06e, 0x7cd4d138],
    [0xb63c6136, 0x2c8a4ab3], [0xcce411fe, 0x1cbfc3ca],
    [0x83b465d5, 0xd4a0eece], [0xf96c151d, 0xe49567b7],
    [0x76048445, 0xb4cbfc3c], [0x0cdcf48d, 0x84fe7545],
    [0x6fbd6d5e, 0xbd3716b7], [0x15651d96, 0x8d029fce],
    [0x9a0d8cce, 0xdd5c0445], [0xe0d5fc06, 0xed698d3c],
    [0xaf85882d, 0x2576a038], [0xd55df8e5, 0x15432941],
    [0x5a3569bd, 0x451db2ca], [0x20ed1975, 0x75283bb3],
    [0xc49581ea, 0xd523e8c2], [0xbe4df122, 0xe51661bb],
    [0x3125607a, 0xb548fa30], [0x4bfd10b2, 0x857d7349],
    [0x04ad6499, 0x4d625e4d], [0x7e751451, 0x7d57d734],
    [0xf11d8509, 0x2d094cbf], [0x8bc5f5c1, 0x1d3cc5c6],
    [0x12b59265, 0x35897936], [0x686de2ad, 0x05bcf04f],
    [0xe70573f5, 0x55e26bc4], [0x9ddd033d, 0x65d7e2bd],
    [0xd28d7716, 0xadc8cfb9], [0xa85507de, 0x9dfd46c0],
    [0x273d9686, 0xcda3dd4b], [0x5de5e64e, 0xfd965432],
    [0xb99d7ed1, 0x5d9d8743], [0xc3450e19, 0x6da80e3a],
    [0x4c2d9f41, 0x3df695b1], [0x36f5ef89, 0x0dc31cc8],
    [0x79a59ba2, 0xc5dc31cc], [0x037deb6a, 0xf5e9b8b5],
    [0x8c157a32, 0xa5b7233e], [0xf6cd0afa, 0x9582aa47],
    [0x4ad64994, 0xd625e4da], [0x300e395c, 0xe6106da3],
    [0xbf66a804, 0xb64ef628], [0xc5bed8cc, 0x867b7f51],
    [0x8aeeace7, 0x4e645255], [0xf036dc2f, 0x7e51db2c],
    [0x7f5e4d77, 0x2e0f40a7], [0x05863dbf, 0x1e3ac9de],
    [0xe1fea520, 0xbe311aaf], [0x9b26d5e8, 0x8e0493d6],
    [0x144e44b0, 0xde5a085d], [0x6e963478, 0xee6f8124],
    [0x21c64053, 0x2670ac20], [0x5b1e309b, 0x16452559],
    [0xd476a1c3, 0x461bbed2], [0xaeaed10b, 0x762e37ab],
    [0x37deb6af, 0x5e9b8b5b], [0x4d06c667, 0x6eae0222],
    [0xc26e573f, 0x3ef099a9], [0xb8b627f7, 0x0ec510d0],
    [0xf7e653dc, 0xc6da3dd4], [0x8d3e2314, 0xf6efb4ad],
    [0x0256b24c, 0xa6b12f26], [0x788ec284, 0x9684a65f],
    [0x9cf65a1b, 0x368f752e], [0xe62e2ad3, 0x06bafc57],
    [0x6946bb8b, 0x56e467dc], [0x139ecb43, 0x66d1eea5],
    [0x5ccebf68, 0xaecec3a1], [0x2616cfa0, 0x9efb4ad8],
    [0xa97e5ef8, 0xcea5d153], [0xd3a62e30, 0xfe90582a],
    [0xb0c7b7e3, 0xc7593bd8], [0xca1fc72b, 0xf76cb2a1],
    [0x45775673, 0xa732292a], [0x3faf26bb, 0x9707a053],
    [0x70ff5290, 0x5f188d57], [0x0a272258, 0x6f2d042e],
    [0x854fb300, 0x3f739fa5], [0xff97c3c8, 0x0f4616dc],
    [0x1bef5b57, 0xaf4dc5ad], [0x61372b9f, 0x9f784cd4],
    [0xee5fbac7, 0xcf26d75f], [0x9487ca0f, 0xff135e26],
    [0xdbd7be24, 0x370c7322], [0xa10fceec, 0x0739fa5b],
    [0x2e675fb4, 0x576761d0], [0x54bf2f7c, 0x6752e8a9],
    [0xcdcf48d8, 0x4fe75459], [0xb7173810, 0x7fd2dd20],
    [0x387fa948, 0x2f8c46ab], [0x42a7d980, 0x1fb9cfd2],
    [0x0df7adab, 0xd7a6e2d6], [0x772fdd63, 0xe7936baf],
    [0xf8474c3b, 0xb7cdf024], [0x829f3cf3, 0x87f8795d],
    [0x66e7a46c, 0x27f3aa2c], [0x1c3fd4a4, 0x17c62355],
    [0x935745fc, 0x4798b8de], [0xe98f3534, 0x77ad31a7],
    [0xa6df411f, 0xbfb21ca3], [0xdc0731d7, 0x8f8795da],
    [0x536fa08f, 0xdfd90e51], [0x29b7d047, 0xefec8728]
    );

sub crc64($$) {
    my ($cv, $str) = @_;
    my $c;
    my @cc = @$cv;
    $cc[0] %= 4294967296;
    $cc[1] %= 4294967296;

    foreach $c (unpack("C*", $str)) {
	my @ct = @{$crc64_tab[($cc[1] & 0xff) ^ $c]};

	$cc[1] = $ct[1] ^
	    ((($cc[1] & 0xffffff00) >> 8) | (($cc[0] & 0xff) << 24));
	$cc[0] = $ct[0] ^ (($cc[0] & 0xffffff00) >> 8);
    }

    return @cc;
}
